import { Injectable } from '@nestjs/common';
import { CommonService } from '../common/common.service';
import { Permission as PermissionEntity } from '@/entity/Permission';
import { InjectRepository } from '@nestjs/typeorm';
import { DataSource, Like, Repository } from 'typeorm';
import { RolePermission as RolePermissionEntity } from '@/entity/RolePermission';

@Injectable()
export class PermissionService extends CommonService<PermissionEntity> {
  constructor(
    @InjectRepository(PermissionEntity)
    private readonly permissionRepository: Repository<PermissionEntity>,
    private dataSource: DataSource,
  ) {
    super(permissionRepository);
  }

  // 更新权限
  async updatePermissionById(
    permissionId: number,
    toUpdatePermission: Partial<PermissionEntity>,
    parentId: number,
  ) {
    // parentId === 0 => 成为一级菜单，
    let newParentPath = '';
    if (Number(parentId) !== 0) {
      const parentPermissionEntity = await this.permissionRepository.findOne({
        where: { id: parentId },
      });
      newParentPath = `${parentPermissionEntity.idPath}/${parentPermissionEntity.id}`;
    }

    const currentPermissionEntity = await this.permissionRepository.findOne({
      where: { id: permissionId },
    });
    const oldParentPath = currentPermissionEntity.idPath;
    // 开启事务
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    try {
      // 开启事务
      await queryRunner.startTransaction();
      // 更新当前权限节点的信息
      await queryRunner.manager
        .getRepository(PermissionEntity)
        .createQueryBuilder()
        .update()
        .set({
          ...toUpdatePermission,
          idPath: newParentPath,
          // 严格控制funType类型不变
          funcType: currentPermissionEntity.funcType,
        })
        .where('id = :permissionId', { permissionId })
        .execute();
      // 更新所有旧节点的idPath路径
      await queryRunner.manager
        .getRepository(PermissionEntity)
        .createQueryBuilder()
        .update()
        .set({
          idPath() {
            return `INSERT(id_path, 1, ${oldParentPath.length}, '${newParentPath}')`;
          },
        })
        .where(`id_path LIKE :parentPath`, {
          parentPath: `${oldParentPath}/${currentPermissionEntity.id}%`,
        })
        .execute(),
        await queryRunner.commitTransaction();
    } catch (error) {
      // 发生错误回滚
      await queryRunner.rollbackTransaction();
      throw error;
    }
    // 释放
    await queryRunner.release();
  }

  // 删除权限
  async deletePermissionById(permissionId: number) {
    const currentPermissionEntity = await this.permissionRepository.findOne({
      where: { id: permissionId },
    });

    const permissionChildren = await this.permissionRepository.find({
      where: {
        idPath: Like(
          `${currentPermissionEntity.idPath}/${currentPermissionEntity.id}%`,
        ),
      },
    });
    const toDeletePermissionIds = [
      ...permissionChildren.map((item) => item.id),
      permissionId,
    ];
    // 开启事务
    const queryRunner = this.dataSource.createQueryRunner();
    await queryRunner.connect();
    try {
      // 开启事务
      await queryRunner.startTransaction();
      // 删除所有跟 toDeletePermissionIds 有关的 角色权限关系
      await queryRunner.manager
        .getRepository(RolePermissionEntity)
        .createQueryBuilder()
        .delete()
        .where('permission_id in (:...permissionIds)', {
          permissionIds: toDeletePermissionIds,
        })
        .execute();
      // 这个时候才能安全的删除所有的权限
      await queryRunner.manager
        .getRepository(PermissionEntity)
        .createQueryBuilder()
        .delete()
        .whereInIds(toDeletePermissionIds)
        .execute();
      await queryRunner.commitTransaction();
    } catch (error) {
      // 发生错误回滚
      await queryRunner.rollbackTransaction();
      throw error;
    }
    // 释放
    await queryRunner.release();
  }
}
